package cn.com.easy.pay.weixinpay.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.com.easy.dto.MessageDTO;
import cn.com.easy.exception.BusinessException;
import cn.com.easy.pay.weixinpay.config.WeixinPayConfig;
import cn.com.easy.utils.ResponseOutputUtils;

import com.tencent.common.Configure;
import com.tencent.common.Util;
import com.tencent.protocol.reverse_protocol.ReverseReqData;
import com.tencent.protocol.reverse_protocol.ReverseResData;
import com.tencent.service.ReverseService;

/**
 * 撤销订单基础控制器
 * 
 * @author nibili 2017年5月12日
 * 
 */
public abstract class WeixinPayReverseBaseController {

	private Logger logger = LoggerFactory.getLogger(WeixinPayReverseBaseController.class);

	/** 订单查询服务类 ，sdk */
	private ReverseService reverseService;

	/**
	 * 获取微信支付配置<br/>
	 * 
	 * @param httpRequest
	 * @return
	 * @throws BusinessException
	 * @author nibili 2017年5月12日
	 */
	public abstract WeixinPayConfig getWeixinPayConfig(HttpServletRequest httpRequest) throws BusinessException;

	/**
	 * 进行一次撤销操作
	 * 
	 * @param outTradeNo
	 *            商户系统内部的订单号,32个字符内可包含字母, [确保在商户系统唯一]
	 * @return 该订单是否支付成功
	 * @throws Exception
	 */
	@RequestMapping("/reverse")
	public void payQuery(final HttpServletRequest request, final HttpServletResponse response, String outTradeNo) {
		try {
			WeixinPayConfig weixinPayConfig = getWeixinPayConfig(request);
			Configure configure = new Configure();
			configure.setKey(weixinPayConfig.getAppkey());
			configure.setAppID(weixinPayConfig.getAppid());
			configure.setMchID(weixinPayConfig.getMch_id());
			configure.setSubMchID(weixinPayConfig.getSubMchID());
			configure.setCertLocalPath(weixinPayConfig.getCertLocalPath());
			configure.setCertPassword(weixinPayConfig.getCertPassword());
			reverseService = new ReverseService(configure);
			//
			String reverseResponseString;
			ReverseReqData reverseReqData = new ReverseReqData(configure, "", outTradeNo);
			reverseResponseString = reverseService.request(reverseReqData);
			// log.i("撤销API返回的数据如下：");
			// log.i(reverseResponseString);
			// 将从API返回的XML数据映射到Java对象
			ReverseResData reverseResData = (ReverseResData) Util.getObjectFromXML(reverseResponseString, ReverseResData.class);
			if (reverseResData == null) {
				// log.i("支付订单撤销请求逻辑错误，请仔细检测传过去的每一个参数是否合法");
				this.onFailByReturnCodeError(request, response, reverseResData);
				return;
			}
			if (reverseResData.getReturn_code().equals("FAIL")) {
				// 注意：一般这里返回FAIL是出现系统级参数错误，请检测Post给API的数据是否规范合法
				// log.i("支付订单撤销API系统返回失败，失败信息为：" +
				// reverseResData.getReturn_msg());
				this.onFailByReturnCodeFail(request, response, reverseResData);
				return;
			} else {
				if (reverseResData.getResult_code().equals("FAIL")) {
					// log.i("撤销出错，错误码：" + reverseResData.getErr_code() +
					// "     错误信息：" + reverseResData.getErr_code_des());
					if (reverseResData.getRecall().equals("Y")) {
						// 表示需要重试
						onReverseFail(request, response, reverseResData);
					} else {
						// 表示不需要重试，也可以当作是撤销成功
						onReverseSuccess(request, response, reverseResData);
					}
				} else {
					// 查询成功，打印交易状态
					// log.i("支付订单撤销成功");
					onReverseSuccess(request, response, reverseResData);
				}
			}
		} catch (BusinessException ex) {
			logger.error("撤销订单发生异常(自定义异常):" + ex.getMessage(), ex);
			// 错误
			ResponseOutputUtils.renderJson(response, MessageDTO.newInstance("", false, ex.getMessage()));
		} catch (Exception ex) {
			logger.error("撤销订单发生异常:" + ex.getMessage(), ex);
			// 错误
			ResponseOutputUtils.renderJson(response, MessageDTO.newInstance("", false, ex.getMessage()));
		}
	}

	/**
	 * 撤销失败<br/>
	 * 例：撤销失败，请重试
	 * 
	 * @param request
	 * @param response
	 * @param reverseResData
	 * @author nibili 2017年5月14日
	 */
	public abstract void onReverseFail(HttpServletRequest request, HttpServletResponse response, ReverseResData reverseResData);

	/**
	 * 撤销订单成功
	 * 
	 * @param request
	 * @param response
	 * @param reverseResData
	 * @author nibili 2017年5月14日
	 */
	public abstract void onReverseSuccess(HttpServletRequest request, HttpServletResponse response, ReverseResData reverseResData);

	/**
	 * API返回ReturnCode不合法，支付请求逻辑错误，请仔细检测传过去的每一个参数是否合法，或是看API能否被正常访问 <br/>
	 * 例：请检查每一个参数是否合法
	 * 
	 * @param request
	 * @param response
	 * @param reverseResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onFailByReturnCodeError(HttpServletRequest request, HttpServletResponse response, ReverseResData reverseResData);

	/**
	 * API返回ReturnCode为FAIL，支付API系统返回失败，请检测Post给API的数据是否规范合法 <br/>
	 * 例 ： 请检测Post给API的数据是否规范合法
	 * 
	 * @param request
	 * @param response
	 * @param reverseResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onFailByReturnCodeFail(HttpServletRequest request, HttpServletResponse response, ReverseResData reverseResData);

}
